home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Hot Mix 17
/
Hot Mix 17.iso
/
HM17_SGI
/
research
/
lib
/
eigenvec.pro
< prev
next >
Wrap
Text File
|
1997-07-08
|
9KB
|
207 lines
;$Id: eigenvec.pro,v 1.4 1997/01/15 03:11:50 ali Exp $
;
; Copyright (c) 1994-1997, Research Systems, Inc. All rights reserved.
; Unauthorized reproduction prohibited.
;+
; NAME:
; EIGENVEC
;
; PURPOSE:
; This function computes the eigenvectors of an N by N real, non-
; symmetric array using inverse subspace iteration. The result is
; a complex array with a column dimension equal to N and a row
; dimension equal to the number of eigenvalues.
;
; CATEGORY:
; Linear Algebra / Eigensystems
;
; CALLING SEQUENCE:
; Result = Eigenvec(A, Eval)
;
; INPUTS:
; A: An N by N nonsymmetric array of type float or double.
;
; EVAL: An N-element complex vector of eigenvalues.
;
; KEYWORD PARAMETERS:
; DOUBLE: If set to a non-zero value, computations are done in
; double precision arithmetic.
;
; ITMAX: The number of iterations performed in the computation
; of each eigenvector. The default value is 4.
;
; RESIDUAL: Use this keyword to specify a named variable which returns
; the residuals for each eigenvalue/eigenvector(lambda/x) pair.
; The residual is based on the definition Ax - (lambda)x = 0
; and is an array of the same size and type as RESULT. The rows
; this array correspond to the residuals for each eigenvalue/
; eigenvector pair. This keyword must be initialized to a non-
; zero value before calling EIGENVEC if the residuals are
; desired.
;
; EXAMPLE:
; Define an N by N real, nonsymmetric array.
; a = [[1.0, -2.0, -4.0, 1.0], $
; [0.0, -2.0, 3.0, 4.0], $
; [2.0, -6.0, -1.0, 4.0], $
; [3.0, -3.0, 1.0, -2.0]]
;
; Compute the eigenvalues of A using double-precision complex arithmetic.
; eval = HQR(ELMHES(a), /double)
;
; Print the eigenvalues. The correct solution should be:
; (0.26366259, -6.1925899), (0.26366259, 6.1925899), $
; (-4.9384492, 0.0000000), (0.41112397, 0.0000000)
; print, eval
;
; Compute the eigenvectors of A. The eigenvectors are returned in the
; rows of EVEC. The residual keyword must be initialized as a nonzero
; value prior to calling EIGENVEC.
; residual = 1
; result = EIGENVEC(a, eval, residual = residual)
;
; Print the eigenvectors.
; print, evec(*,0), evec(*,1), evec(*,2), evec(*,3)
;
; The accuracy of each eigenvalue/eigenvector (lamda/x)
; pair may be checked by printing the residual array. This array is the
; same size and type as RESULT and returns the residuals as its rows.
; The residual is based on the mathematical definition of an eigenvector,
; Ax - (lambda)x = 0. All residual values should be floating-point zeros.
; print, residual
;
; PROCEDURE:
; EIGENVEC computes the set of eigenvectors that correspond to a given
; set of eigenvalues using Inverse Subspace Iteration. The eigenvectors
; are computed up to a scale factor and are of Euclidean length. The
; existence and uniqueness of eigenvectors are not guaranteed.
;
; MODIFICATION HISTORY:
; Written by: GGS, RSI, December 1994
; Modified: GGS, RSI, April 1996
; Modified keyword checking and use of double precision.
;-
FUNCTION EigenVec, A, Eval, Double = Double, ItMax = ItMax, $
Residual = Residual
ON_ERROR, 2 ;Return to caller if error occurs.
if N_PARAMS() ne 2 then $
MESSAGE, "Incorrect number of input arguments."
TypeA = SIZE(A)
TypeEval = SIZE(Eval)
if TypeA[1] ne TypeA[2] then $
MESSAGE, "Input array must be square."
if TypeA[3] ne 4 and TypeA[3] ne 5 then $
MESSAGE, "Input array must be float or double."
if TypeEval[TypeEval[0]+1] ne 6 and TypeEval[TypeEval[0]+1] ne 9 then $
MESSAGE, "Eigenvalues must be complex or double-complex."
Enum = TypeEval[TypeEval[0]+2] ;Number of eigenvalues.
if TypeA[2] ne Enum then $
MESSAGE, "Input array and eigenvalues are of incompatible size."
;If the DOUBLE keyword is not set then the internal precision and
;result are determined by the type of input.
if N_ELEMENTS(Double) eq 0 then $
Double = (TypeA[TypeA[0]+1] eq 5 or TypeEval[TypeEval[0]+1] eq 9)
if N_ELEMENTS(ItMax) eq 0 then ItMax = 4
Diag = LINDGEN(TypeA[1]) * (TypeA[1]+1) ;Diagonal indices.
;Double Precision.
if Double ne 0 then begin
Evec = DCOMPLEXARR(TypeA[1], Enum) ;Eigenvector storage array with number
;of rows equal to number of eigenvalues.
for k = 0, Enum - 1 do begin
Alud = A ;Create a copy of the array for next eigenvalue computation.
if IMAGINARY(Eval[k]) ne 0 then begin ;Complex eigenvalue.
Alud = DCOMPLEX(Alud)
Alud[Diag] = Alud[Diag] - Eval[k]
;Avoid intermediate variables. re = DOUBLE(Alud) im = IMAGINARY(Alud)
Comp = [[DOUBLE(Alud), -IMAGINARY(Alud)], $
[IMAGINARY(Alud), DOUBLE(Alud)]]
;Initial eigenvector.
B = REPLICATE(1.0d, 2*TypeA[1]) / SQRT(2.0d * TypeA[1])
LUDC, Comp, Index, DOUBLE = DOUBLE
it = 0
while it lt ItMax do begin ;Iteratively compute the eigenvector.
X = LUSOL(Comp, Index, B, DOUBLE = DOUBLE)
B = X / SQRT(TOTAL(X^2, 1, DOUBLE = DOUBLE)) ;Normalize eigenvector.
it = it + 1
endwhile
;Row vector storage.
Evec[*, k] = DCOMPLEX(B[0:TypeA[1]-1], B[TypeA[1]:*])
endif else begin ;Real eigenvalue
Alud[Diag] = Alud[Diag] - DOUBLE(Eval[k])
B = REPLICATE(1.0d, TypeA[1]) / SQRT(TypeA[1]+0.0d)
LUDC, Alud, Index, DOUBLE = DOUBLE
it = 0
while it lt ItMax do begin
X = LUSOL(Alud, Index, B, DOUBLE = DOUBLE)
B = X / SQRT(TOTAL(X^2, 1, DOUBLE = DOUBLE)) ;Normalize eigenvector.
it = it + 1
endwhile
Evec[*, k] = DCOMPLEX(B, 0.0d0) ;Row vector storage.
endelse
endfor
if keyword_set(Residual) then begin ;Compute eigenvalue/vector residuals.
;Because RESIDUAL is a keyword that envokes functionality and returns
;a named variable, it must be initialized before calling EIGENVEC().
Residual = DCOMPLEXARR(TypeA[1], Enum) ;Dimensioned the same as Evec.
for k = 0, Enum - 1 do $
Residual[*,k] = (A##Evec[*,k]) - (Eval[k] * Evec[*,k])
endif
endif else begin ;Single Precision.
Evec = COMPLEXARR(TypeA[1], Enum) ;Eigenvector storage array.
for k = 0, Enum - 1 do begin
Alud = A ;Create a copy of the array for next eigenvalue computation.
if IMAGINARY(Eval[k]) ne 0 then begin ;Complex eigenvalue.
Alud = COMPLEX(Alud)
Alud[Diag] = Alud[Diag] - Eval[k]
;Avoid intermediate variables. re = FLOAT(Alud) im = IMAGINARY(Alud)
Comp = [[FLOAT(Alud), -IMAGINARY(Alud)], $
[IMAGINARY(Alud), FLOAT(Alud)]]
;Initial eigenvector.
B = REPLICATE(1.0, 2*TypeA[1]) / SQRT(2.0 * TypeA[1])
LUDC, Comp, Index, DOUBLE = DOUBLE
it = 0
while it lt ItMax do begin ;Iteratively compute the eigenvector.
X = LUSOL(Comp, Index, B, DOUBLE = DOUBLE)
B = X / SQRT(TOTAL(X^2, 1)) ;Normalize eigenvector.
it = it + 1
endwhile
;Row vector storage.
Evec[*, k] = COMPLEX(B[0:TypeA[1]-1], B[TypeA[1]:*])
endif else begin ;Real eigenvalue
Alud[Diag] = Alud[Diag] - FLOAT(Eval[k])
B = REPLICATE(1.0, TypeA[1]) / SQRT(TypeA[1])
LUDC, Alud, Index, DOUBLE = DOUBLE
it = 0
while it lt ItMax do begin
X = LUSOL(Alud, Index, B, DOUBLE = DOUBLE)
B = X / SQRT(TOTAL(X^2, 1)) ;Normalize eigenvector.
it = it + 1
endwhile
Evec[*, k] = COMPLEX(B, 0.0) ;Row vector storage.
endelse
endfor
if keyword_set(Residual) then begin ;Compute eigenvalue/vector residuals.
;Because RESIDUAL is a keyword that envokes functionality and returns
;a named variable, it must be initialized before calling EIGENVEC().
Residual = COMPLEXARR(TypeA[1], Enum) ;Dimensioned the same as Evec.
for k = 0, Enum - 1 do $
Residual[*,k] = (A##Evec[*,k]) - (Eval[k] * Evec[*,k])
endif
endelse
if Double eq 0 then RETURN, COMPLEX(Evec) else RETURN, Evec
END